package cn.yeziji.forum.config.aspect;

import cn.yeziji.forum.annoataion.RemoveCache;
import cn.yeziji.forum.annoataion.SaveCache;
import cn.yeziji.forum.common.enums.ForumCommonStatus;
import cn.yeziji.forum.common.key.CacheMode;
import cn.yeziji.forum.exception.ForumException;
import cn.yeziji.forum.utils.CacheUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 缓存监听器 [测试]
 *
 * @author gzkemays
 * @since 2022/11/19 11:46 AM
 */
@Aspect
@Slf4j
@Configuration
public class CacheAspect {
  @Resource CacheUtils cacheUtils;

  @After(value = "@annotation(remove)")
  public void removeAfter(JoinPoint joinPoint, RemoveCache remove) {
    String[] keys = remove.value();
    String[] jsonKeys = remove.jsonKey();
    StringBuilder jsonValue = new StringBuilder();
    String joinery = remove.joinery();

    int mode = remove.mode();
    if (StringUtils.isNotBlank(jsonKeys[0])) {
      // 从请求参数中获取 JSON KEY 对应的值进行拼接
      Object[] args = joinPoint.getArgs();
      if (args.length > 0) {
        for (Object arg : args) {
          jsonValue.append(buildGetJsonValue(arg, joinery, jsonKeys));
        }
      }
    } else {
      jsonValue.append(joinery);
    }
    for (String key : keys) {
      if (StringUtils.isNotBlank(joinery)) {
        // 如果拼接符存在先拼接
        key += jsonValue.toString();
      }

      if (mode == CacheMode.OPS_VALUE) {
        if (remove.blur()) {
          cacheUtils.blurPrefixRemove(key);
        } else {
          cacheUtils.remove(key);
        }
      } else if (mode == CacheMode.OPS_HASH) {
        String hashKey = remove.hashKey();
        if (StringUtils.isNotBlank(hashKey)) {
          cacheUtils.removeHash(key, hashKey);
        } else if (remove.blur()) {
          cacheUtils.blurPrefixRemove(key);
        } else {
          cacheUtils.remove(key);
        }
      }
    }
  }

  @AfterReturning(value = "@annotation(response)", returning = "obj")
  public void saveAfterReturning(JoinPoint joinPoint, SaveCache response, Object obj) {
    if (obj == null) {
      // cache 存值时，必须不为 null
      return;
    }
    String[] keys = response.value();
    String[] jsonKeys = response.jsonKey();
    StringBuilder jsonValue = new StringBuilder();
    String joinery = response.joinery();

    int mode = response.mode();
    if (StringUtils.isNotBlank(jsonKeys[0])) {
      // 从请求参数中获取 JSON KEY 对应的值进行拼接
      Object[] args = joinPoint.getArgs();
      if (args.length > 0) {
        for (Object arg : args) {
          jsonValue.append(buildGetJsonValue(arg, joinery, jsonKeys));
        }
      }
    } else {
      jsonValue.append(joinery);
    }

    int time = response.time();
    TimeUnit unit = response.unit();
    for (String key : keys) {
      if (StringUtils.isNotBlank(joinery)) {
        // 如果拼接符存在先拼接
        key += jsonValue.toString();
      }
      if (response.joinReqParam()) {
        // 拼接请求参数
        key += joinPoint.getArgs()[0];
      }

      if (mode == CacheMode.OPS_VALUE) {
        Object cacheData = cacheUtils.get(key);
        if (cacheData != null && response.refresh()) {
          cacheUtils.set(key, obj, time, unit);
        } else if (cacheData == null) {
          cacheUtils.set(key, obj, time, unit);
        }
      } else if (mode == CacheMode.OPS_HASH) {
        String hashKey = response.hashKey();
        // response hash key 必须存在
        if (StringUtils.isBlank(hashKey)) {
          throw new ForumException(ForumCommonStatus.DATA_ERROR);
        }
        Object cacheData = cacheUtils.getByHash(key, hashKey);
        if (cacheData != null && response.refresh()) {
          cacheUtils.setHash(key, response.hashKey(), obj, time, unit);
        } else if (cacheData == null) {
          cacheUtils.setHash(key, response.hashKey(), obj, time, unit);
        }
      }
    }
  }

  public String buildGetJsonValue(Object joinPointReqValue, String joinery, String... jsonKeys) {
    try {
      // 从请求参数中获取 JSON KEY 对应的值进行拼接
      JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(joinPointReqValue));
      boolean joineryBlank = StringUtils.isBlank(joinery);
      StringBuilder jsonKey = new StringBuilder();
      // key 必须为字符串
      for (String key : jsonKeys) {
        if (joineryBlank) {
          jsonKey.append(jsonObject.get(key));
        } else {
          jsonKey.append(joinery).append(jsonObject.get(key));
        }
      }
      return jsonKey.toString();
    } catch (Exception e) {
      // 非 JSON 对象
      return String.valueOf(joinPointReqValue);
    }
  }
}
